﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Drawing;
using Ultima;
using Expand;
using System.Windows.Forms;
using System.ComponentModel;
using System.Reflection;
using SpellCaster3.Core;

namespace SpellCaster3.Forms.Controls
{
    [DefaultBindingProperty("Value")]
    public partial class HotkeyControl : UserControl, IInputOutput, INotifyPropertyChanged
    {
        private static StringCollection CustomAllowedKeys = new StringCollection();

        private bool _Resetting;

        static HotkeyControl()
        {
            CustomAllowedKeys.Add("Nessuno");
            foreach (Keys key in ButtonMacro.AllowedKeys)
                switch (key)
                {
                    case Keys.Shift:
                    case Keys.Control:
                    case Keys.Alt:
                        break;
                    default:
                        CustomAllowedKeys.Add(Enum.GetName(key.GetType(), key));
                        break;
                }
        }

        public HotkeyControl()
        {
            _Resetting = true;
            InitializeComponent();
            keyComboBox.DataSource = CustomAllowedKeys;
            _Resetting = false;
        }

        public bool Shift
        {
            get { return shiftCheckBox.Checked; }
            set { shiftCheckBox.Checked = value; }
        }

        public bool Control
        {
            get { return controlCheckBox.Checked; }
            set { controlCheckBox.Checked = value; }
        }

        public bool Alt
        {
            get { return altCheckBox.Checked; }
            set { altCheckBox.Checked = value; }
        }

        public Keys Key
        {
            get { return GetKeyFromComboBox(); }
            set { SelectKeyComboBoxIndex(value); }
        }

        private void SelectKeyComboBoxIndex(Keys key)
        {
            if (key == Keys.None)
                keyComboBox.SelectedIndex = 0;
            else
            {
                int res = keyComboBox.Items.IndexOf(Enum.GetName(key.GetType(), key));
                if (res > 0)
                    keyComboBox.SelectedIndex = res;
            }
        }

        private Keys GetKeyFromComboBox()
        {
            return keyComboBox.SelectedIndex == 0 ? Keys.None : (Keys)Enum.Parse(typeof(Keys), CustomAllowedKeys[keyComboBox.SelectedIndex]);
        }

        public virtual void Reset()
        {
            SetValue(false, false, false, Keys.None);
            FireValueChanged();
        }

        private void FireValueChanged()
        {
            if (_Resetting) return;
            OnValueChanged(this, EventArgs.Empty);
            OnIOValueChanged(this, new LastValueEventArgs<object>(_LastValue));
            OnPropertyChanged(this, new PropertyChangedEventArgs("Value"));
        }

        private Keys _LastValue = Keys.None;

        public void SetValue(bool shift, bool control, bool alt, Keys key)
        {
            _Resetting = true;
            shiftCheckBox.Checked = shift;
            controlCheckBox.Checked = control;
            altCheckBox.Checked = alt;
            SelectKeyComboBoxIndex(key);
            _Resetting = false;
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        [Bindable(true)]
        public Keys Value
        {
            get
            {
                Keys tmp = Keys.None;
                if (Shift)
                    tmp |= Keys.Shift;
                if (Control)
                    tmp |= Keys.Control;
                if (Alt)
                    tmp |= Keys.Alt;
                tmp |= Key;
                return tmp;
            }

            set
            {
                if (!ButtonMacro.ValidKeysCombo(value))
                    throw new ArgumentException("value doesn't contain valid keys");

                _LastValue = Value;

                bool res1, res2, res3;
                Keys key = value & ~(Keys.Shift | Keys.Control | Keys.Alt);
                res1 = value.HasFlag(Keys.Shift);
                res2 = value.HasFlag(Keys.Control);
                res3 = value.HasFlag(Keys.Alt);

                SetValue(res1, res2, res3, key);
                FireValueChanged();
            }
        }

        protected virtual void OnValueChanged(object sender, EventArgs e)
        {
            if (ValueChanged != null) ValueChanged(sender, e);
        }

        public event EventHandler ValueChanged;

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        public object IOValue
        {
            get { return (object)Value; }
            set
            {
                Value = (Keys)value;
            }
        }

        protected virtual void OnIOValueChanged(object sender, LastValueEventArgs<object> e)
        {
            if (IOValueChanged != null) IOValueChanged(this, e);
        }

        public event EventHandler<LastValueEventArgs<object>> IOValueChanged;

        private void shiftCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            FireValueChanged();
        }

        private void controlCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            FireValueChanged();
        }

        private void altCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            FireValueChanged();
        }

        private void keyComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            FireValueChanged();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null) PropertyChanged(sender, e);
        }
    }
}
